
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>

#include "RPC.hxx"
#define WINCEMACRO
#include "XAPI.h"

#include <pkfuncs.h>
//#define WINCEMACRO
//#include <psyscall.h>



#ifdef __cplusplus
extern "C" {
#endif



//
// yapi
//

void TstFun();
int TstFunVal(int t);
void TstFunPtr(TCHAR* psz);
void ExitYAPITst();

DWORD g_dwYAPISetId=(DWORD)-1;

__inline void YAPI_TstFun()
{
	IMPLICIT_DECL(void, g_dwYAPISetId, 1, (void))();
}
__inline int YAPI_TstFunVal(int t)
{
	return IMPLICIT_DECL(int, g_dwYAPISetId, 2, (int))(t);
}
__inline void YAPI_TstFunPtr(TCHAR* psz)
{
	IMPLICIT_DECL(void, g_dwYAPISetId, 3, (TCHAR*))(psz);
}
__inline void YAPI_ExitYAPITst()
{
	IMPLICIT_DECL(void, g_dwYAPISetId, 4, (void))();
}

void* g_APIFnS[]=
{
	0,
	(void*)TstFun,
	(void*)TstFunVal,
	(void*)TstFunPtr,
	(void*)ExitYAPITst,
};

DWORD g_APISigS[]=
{
	0,
    FNSIG0(),
    FNSIG1(DW),
    FNSIG1(PTR),
    FNSIG0(),
};
#ifdef __cplusplus
}
#endif

DWORD g_dwProcId;
void TstFun()
{
	RETAILMSG(1, (TEXT("Proc:0x%x TstFun\r\n"), g_dwProcId));
};

int TstFunVal(int t)
{
	RETAILMSG(1, (TEXT("Proc:0x%x TstFunVal val:0x%x\r\n"), g_dwProcId, t));
	return t;
};

void TstFunPtr(TCHAR* psz)
{
	RETAILMSG(1, (TEXT("Proc:0x%x TstFunPtr prt:%s\r\n"), g_dwProcId, psz));
};

BOOL g_fExitYAPITst=FALSE;
void ExitYAPITst()
{
	RETAILMSG(1, (TEXT("Proc:0x%x ExitYAPITst\r\n"), g_dwProcId));
	g_fExitYAPITst=TRUE;
};




HANDLE g_hTgt=NULL;

DWORD GetModulBaseAddr(TCHAR* pszProc, TCHAR* pszMod)
{
	DWORD dwRet=(DWORD)-1;

	//
	// find process
	HANDLE hSnap=CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0);
	ASSERT(INVALID_HANDLE_VALUE != hSnap);

	PROCESSENTRY32 procEntry;
	procEntry.dwSize=sizeof(procEntry);
	BOOL fRet=Process32First(hSnap, &procEntry);
	while(fRet)
	{
		if(0==_tcsicmp(pszProc, procEntry.szExeFile) )
		{
			DEBUGMSG(1, (TEXT("find process %s\r\n"), procEntry.szExeFile));
			break; 
		}

		fRet=Process32Next(hSnap, &procEntry);
	}

	CloseToolhelp32Snapshot(hSnap);

	if(!fRet)
	{
		RETAILMSG(1, (TEXT("can't find proc:%s\r\n"), pszProc));
		return dwRet;
	}


	//
	// find module
	hSnap=CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, procEntry.th32ProcessID);
	ASSERT(INVALID_HANDLE_VALUE != hSnap);

	MODULEENTRY32 moduleEntry;
	moduleEntry.dwSize=sizeof(moduleEntry);
	fRet=Module32First(hSnap, &moduleEntry);
	while(fRet)
	{
		if(0==_tcsicmp(pszMod, moduleEntry.szModule) )
		{
			DEBUGMSG(1, (TEXT("find module %s\r\n"), moduleEntry.szModule));
			break; 
		}

		fRet=Module32Next(hSnap, &moduleEntry);
	}

	CloseToolhelp32Snapshot(hSnap);

	if(!fRet)
	{
		RETAILMSG(1, (TEXT("can't find module:%s\r\n"), pszMod));
		return dwRet;
	}

	return (DWORD)moduleEntry.modBaseAddr;
}

HANDLE GetProcHandle(TCHAR* pszProc, BOOL fIncludeSelf)
{
	HANDLE hRet=NULL;

	HANDLE hSnap=CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0);
	if(INVALID_HANDLE_VALUE == hSnap)
	{
		RETAILMSG(1, (TEXT("CreateToolhelp32Snapshot faild ErrCode:%d\r\n"), GetLastError()));
		return hRet;
	}

	PROCESSENTRY32 procEntry;
	procEntry.dwSize=sizeof(procEntry);
	BOOL fRet=Process32First(hSnap, &procEntry);
	while(fRet)
	{
		if(0==_tcsicmp(pszProc, procEntry.szExeFile) )
		{
			if( (fIncludeSelf)
				|| (GetCurrentProcessId()!=procEntry.th32ProcessID) )
			{
				RETAILMSG(1, (TEXT("find process %s\r\n"), procEntry.szExeFile));
				hRet=OpenProcess(0, FALSE, procEntry.th32ProcessID);
				break; 
			}
		}

		fRet=Process32Next(hSnap, &procEntry);
	}

	CloseToolhelp32Snapshot(hSnap);

	return hRet;
}

BOOL YAPITst()
{
	DWORD dwPerm;
	HANDLE hYAPISet;
	BOOL fRet=FALSE;

	dwPerm=GetCurrentPermissions();
//	SetProcPermissions(0xffffffff);

	hYAPISet=CreateAPISet( "YAPI", sizeof(g_APIFnS)/sizeof(g_APIFnS[0]), (PFNVOID*)&g_APIFnS, g_APISigS);
	if(!hYAPISet)
	{
		RETAILMSG(1, (TEXT("CreateAPISet ErrCode:%d\r\n"), GetLastError()));
		return FALSE;
	}

	do
	{
		int iYAPIRet=XAPI_SetYAPIHandlProc(hYAPISet, g_hTgt);
		if(iYAPIRet<0)
		{
			RETAILMSG(1, (TEXT("XAPI_SetYAPIHandlProc ErrCode:%d\r\n"), iYAPIRet));
			break;
		}

		for(DWORD dwAPISetId=NUM_SYS_HANDLES-1;  dwAPISetId>SH_LASTRESERVED; dwAPISetId--)
		{
			if(RegisterAPISet(hYAPISet, dwAPISetId))
			{
				g_dwYAPISetId=dwAPISetId;
				break;
			}
		}

		if(g_dwYAPISetId==(DWORD)-1)
		{
			RETAILMSG(1, (TEXT("Can't RegisterAPISet ErrCode:%d\r\n"), GetLastError()));
			break;
		}


		RETAILMSG(1, (TEXT("call YAPI_TstFun\r\n")));
		YAPI_TstFun();

		RETAILMSG(1, (TEXT("call YAPI_TstFunVal return:%d\r\n"), YAPI_TstFunVal(dwPerm)));
		
		RETAILMSG(1, (TEXT("call YAPI_TstFunPtr\r\n")));
		YAPI_TstFunPtr(TEXT("YAPI_TstFunPtr\r\n"));

		fRet=TRUE;
	}while(0);

	if(hYAPISet)
	{
		CloseHandle(hYAPISet);
	}

	return fRet;
}

BOOL XAPITst()
{
	int iXAPIRet;
	ParaInfo paraInfoS[8];

	RETAILMSG(1, (TEXT("call XAPI_TstFun\r\n")));
	iXAPIRet=XAPI_DispatchCall(g_hTgt, (DWORD)(&TstFun), 0, NULL);
	RETAILMSG(1, (TEXT("return :%d\r\n"), iXAPIRet));

	paraInfoS[0].dir=PARA_DIR_IN;
	paraInfoS[0].type=PARA_TYPE_VAL;
	paraInfoS[0].len=sizeof(int);
	paraInfoS[0].para=-1;
	RETAILMSG(1, (TEXT("call XAPI_TstFunVal\r\n")));
	iXAPIRet=XAPI_DispatchCall(g_hTgt, (DWORD)(&TstFunVal), 1, paraInfoS);
	RETAILMSG(1, (TEXT("return :%d\r\n"), iXAPIRet));

	paraInfoS[0].dir=PARA_DIR_IN;
	paraInfoS[0].type=PARA_TYPE_PTR;
	paraInfoS[0].len=(_tcslen(TEXT("XAPI_TstFunPtr\r\n"))+1)*sizeof(TCHAR);
	paraInfoS[0].para=(DWORD)TEXT("XAPI_TstFunPtr\r\n");
	RETAILMSG(1, (TEXT("call XAPI_TstFunPtr\r\n")));
	iXAPIRet=XAPI_DispatchCall(g_hTgt, (DWORD)(&TstFunPtr), 1, paraInfoS);
	RETAILMSG(1, (TEXT("return :%d\r\n"), iXAPIRet));

	DWORD dwBaseAddr=GetModulBaseAddr(TEXT("device.exe"), TEXT("devmgr.dll"));
// 0001:000067f8       IsPowerManagerReady        100077f8 f   pmif:pmif.obj
	if((DWORD)-1!=dwBaseAddr)
	{
		HANDLE hDev=GetProcHandle(TEXT("device.exe"), TRUE);
		RETAILMSG(1, (TEXT("call IsPowerManagerReady\r\n")));
		iXAPIRet=XAPI_DispatchCall(hDev, dwBaseAddr+0x77f8, 0, NULL);
		RETAILMSG(1, (TEXT("return :%d\r\n"), iXAPIRet));
	}

	return TRUE;
}




#if (defined(WIN32) && defined(_CONSOLE))
int _tmain(int argc, const _TCHAR* argv[])
{
#else
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
#endif
	g_dwProcId=GetCurrentProcessId();

	TCHAR szFileName[MAX_PATH];
	GetModuleFileName(hInstance, szFileName, MAX_PATH);
	TCHAR* pszFileName=_tcsrchr(szFileName, '\\');
	if(!pszFileName)
	{
		pszFileName=szFileName;
	}
	else
	{
		pszFileName++;		// skip '\'
	}

	g_hTgt=GetProcHandle(pszFileName, FALSE);
	if(!g_hTgt)
	{
		RETAILMSG(1, (TEXT("the first time tst exe run loop for leave\r\n")));
		while(!g_fExitYAPITst)
		{
			Sleep(1000);
		}
		RETAILMSG(1, (TEXT("exe run out of loop\r\n")));
		return 1;
	}

	XAPITst();
	YAPITst();

	RETAILMSG(1, (TEXT("call YAPI_ExitYAPITst\r\n")));
	XAPI_DispatchCall(g_hTgt, (DWORD)(&ExitYAPITst), 0, NULL);

	if(g_hTgt)
	{
		CloseHandle(g_hTgt);
	}

	return 0;
}

